home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / dig-2.0 / dig-2 / dig.2.0 / dig.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-04  |  14.2 KB  |  528 lines

  1.  
  2.  
  3.  /*******************************************************************
  4.  **      DiG -- Domain Information Groper                          **
  5.  **                                                                **
  6.  **        dig.c - Version 2.0 (9/1/90)                            **
  7.  **                                                                **
  8.  **        Developed by: Steve Hotz & Paul Mockapetris             **
  9.  **        USC Information Sciences Institute (USC-ISI)            **
  10.  **        Marina del Rey, California                              **
  11.  **        1989                                                    **
  12.  **                                                                **
  13.  **        dig.c -                                                 **
  14.  **           Version 2.0 (9/1/90)                                 **
  15.  **               o renamed difftime() difftv() to avoid           **
  16.  **                 clash with ANSI C                              **
  17.  **               o fixed incorrect # args to strcmp,gettimeofday  **
  18.  **               o incorrect length specified to strncmp          **
  19.  **               o fixed broken -sticky -envsa -envset functions  **
  20.  **               o print options/flags redefined & modified       **
  21.  **                                                                **
  22.  **           Version 2.0.beta (5/9/90)                            **
  23.  **               o output format - helpful to `doc`               **
  24.  **               o minor cleanup                                  **
  25.  **               o release to beta testers                        **
  26.  **                                                                **
  27.  **           Version 1.1.beta (10/26/89)                          **
  28.  **               o hanging zone transer (when REFUSED) fixed      **
  29.  **               o trailing dot added to domain names in RDATA    **
  30.  **               o ISI internal                                   **
  31.  **                                                                **
  32.  **           Version 1.0.tmp  (8/27/89)                           **
  33.  **               o Error in prnttime() fixed                      **
  34.  **               o no longer dumps core on large pkts             **
  35.  **               o zone transfer (axfr) added                     **
  36.  **               o -x added for inverse queries                   **
  37.  **                               (i.e. "dig -x 128.9.0.32")       **
  38.  **               o give address of default server                 **
  39.  **               o accept broadcast to server @255.255.255.255    **
  40.  **                                                                **
  41.  **           Version 1.0  (3/27/89)                               **
  42.  **               o original release                               **
  43.  **                                                                **
  44.  **     DiG is Public Domain, and may be used for any purpose as   **
  45.  **     long as this notice is not removed.                        **
  46.  ****                                                            ****
  47.  ****   NOTE: Version 2.0.beta is not for public distribution    ****
  48.  ****                                                            ****
  49.  *******************************************************************/
  50.  
  51.  
  52. #define VERSION 20
  53. #define VSTRING "2.0"
  54.  
  55. #include "hfiles.h"
  56.  
  57. #include <sys/types.h>
  58. #include <netinet/in.h>
  59. #include <stdio.h>
  60. #include RESOLVH
  61. #include <sys/file.h>
  62. #include <sys/stat.h>
  63. #include <ctype.h> 
  64. #include <errno.h>
  65. #include "subr.c"
  66. #include "pflag.h"
  67. #include "options.c"
  68.  
  69. #ifdef RESLOCAL
  70. #include "qtime.c"
  71. #else
  72. #include "qtime.h"
  73. #endif
  74.  
  75. int pfcode = PRF_DEF;
  76. int eecode = 0;
  77. extern char *inet_ntoa();
  78. extern struct state _res;
  79.  
  80. FILE  *qfp;
  81. int sockFD;
  82.  
  83. #define MAXDATA        256   
  84. #define SAVEENV "DiG.env"
  85.  
  86. char *defsrv, *srvmsg;
  87. char defbuf[40] = "default -- ";
  88. char srvbuf[60];
  89.  
  90. #define UC(b)   (((int)b)&0xff)
  91.  
  92.  /*
  93.  ** Take arguments appearing in simple string (from file)
  94.  ** place in char**.
  95.  */
  96. stackarg(y,l)
  97.      char *l;
  98.      char **y;
  99. {
  100.   int done=0;
  101.   while (!done) {
  102.     switch (*l) {
  103.     case '\t':
  104.     case ' ':  l++;    break;
  105.     case NULL:
  106.     case '\n': done++; *y = NULL; break;
  107.     default:   *y++=l;  while (!isspace(*l)) l++;
  108.       if (*l == '\n') done++; *l++ = NULL; *y = NULL;
  109. }}}
  110.  
  111.  
  112. main(argc, argv)
  113.      int argc;
  114.      char **argv;
  115. {
  116.     struct hostent *hp;
  117.     short port = htons(NAMESERVER_PORT);
  118.     char packet[PACKETSZ];
  119.     char answer[PACKETSZ];
  120.     int n;
  121.     char doping[90];
  122.     char pingstr[50];
  123.     char *afile;
  124.     unsigned long tmpaddr;
  125.         char revaddr[10][10];
  126.         int addri, addrj;
  127.     char *addrc;
  128.  
  129.     struct timeval exectime, tv1,tv2,tv3;
  130.     char curhost[30];
  131.  
  132.     char *srv;
  133.     int anyflag = 0;
  134.     int sticky = 0;
  135.     int tmp; 
  136.     int qtype = 1, qclass = 1;
  137.     int addrflag = 0;
  138.     int zone = 0;
  139.         int bytes_out, bytes_in;
  140.  
  141.     char cmd[256];
  142.     char domain[128];
  143.         char msg[120], *msgptr;
  144.     char **vtmp;
  145.     char *args[30];
  146.     char **ax;
  147.     char **ay;
  148.     int once = 1, dofile=0; /* batch -vs- interactive control */
  149.     char fileq[100];
  150.     char *qptr;
  151.     int  fp;
  152.     int wait=0;
  153.     int envset=0, envsave=0;
  154.     int Xpfcode, Tpfcode, Toptions;
  155.     char *Xres, *Tres;
  156.     char *pp;
  157.  
  158.  
  159.     res_init();
  160.     gethostname(curhost,30);
  161.     defsrv = strcat(defbuf, inet_ntoa(_res.nsaddr.sin_addr));
  162.     _res.options |= RES_DEBUG;
  163.     Xres = (char *) malloc(sizeof(_res)+1);
  164.     Tres = (char *) malloc(sizeof(_res)+1);
  165.     bcopy(&_res,Xres,sizeof(struct state));
  166.     Xpfcode=pfcode;
  167.  
  168.  /*
  169.  ** If LOCALDEF in environment, should point to file
  170.  ** containing local favourite defaults.  Also look for file
  171.  ** DiG.env (i.e. SAVEENV) in local directory.
  172.  */
  173.  
  174.     if ((((afile= (char *) getenv("LOCALDEF")) != (char *) NULL) &&
  175.          ((fp=open(afile,O_RDONLY)) > 0)) ||
  176.         ((fp = open(SAVEENV,O_RDONLY)) > 0)) {
  177.       read(fp,Xres,sizeof(struct state));
  178.       read(fp,&Xpfcode,sizeof(int));
  179.       close(fp);
  180.       bcopy(Xres,&_res,sizeof(struct state));
  181.       pfcode = Xpfcode;
  182.     }
  183.  /*
  184.  **   check for batch-mode DiG 
  185.  */
  186.     vtmp = argv; ax=args;
  187.     while (*vtmp != NULL) {
  188.       if (strcmp(*vtmp,"-f") == 0) {
  189.         dofile++; once=0;
  190.         if ((qfp = fopen(*++vtmp,"r")) == NULL) {
  191.           fflush(stdout);
  192.           perror("file open");
  193.           fflush(stderr);
  194.           exit(10);
  195.         }
  196.       } else {
  197.         *ax++ = *vtmp;
  198.       }
  199.       vtmp++;
  200.     }
  201.  
  202.     _res.id = 1;
  203.     gettimeofday(&tv1,NULL);
  204.  
  205.  /*
  206.  **  Main section: once if cmd-line query
  207.  **                while !EOF if batch mode
  208.  */
  209.     *fileq=NULL;
  210.     while ((dofile && (fgets(fileq,100,qfp) !=NULL)) || 
  211.            ((!dofile) && (once--))) 
  212.       {
  213.         if ((*fileq=='\n') || (*fileq=='#') || (*fileq==';'))
  214.           continue; /* ignore blank lines & comments */
  215.  
  216. /*
  217.  * "sticky" requests that before current parsing args
  218.  * return to current "working" environment (X******)
  219.  */
  220.         if (sticky) {
  221.           bcopy(Xres,&_res,sizeof(struct state));
  222.           pfcode = Xpfcode;
  223.         }
  224.  
  225. /* concat cmd-line and file args */
  226.         ay=ax;
  227.         qptr=fileq;
  228.         stackarg(ay,qptr);
  229.  
  230.         /* defaults */
  231.         qtype=qclass=1;
  232.         zone = 0;
  233.         *pingstr=0;
  234.         srv=NULL;
  235.  
  236.         sprintf(cmd,"\n; <<>> DiG %s <<>> ",VSTRING);
  237.         argv = args;
  238. /*
  239.  * More cmd-line options than anyone should ever have to
  240.  * deal with ....
  241.  */
  242.         while (*(++argv) != NULL) { 
  243.           strcat(cmd,*argv); strcat(cmd," ");
  244.           if (**argv == '@') {
  245.         srv = (*argv+1);
  246.         continue;
  247.           }
  248.           if (**argv == '%')
  249.         continue;
  250.           if (**argv == '+') {
  251.         SetOption(*argv+1);
  252.         continue;
  253.           }
  254.      
  255.           if (strncmp(*argv,"-nost",5) == 0) {
  256.         sticky=0;; continue;
  257.           } else if (strncmp(*argv,"-st",3) == 0) {
  258.         sticky++; continue;
  259.           } else if (strncmp(*argv,"-envsa",6) == 0) {
  260.         envsave++; continue;
  261.           } else if (strncmp(*argv,"-envse",6) == 0) {
  262.         envset++; continue;
  263.           }
  264.  
  265.          if (**argv == '-') {
  266.        switch (argv[0][1]) { 
  267.        case 'T': wait = atoi(*++argv);
  268.          break;
  269.        case 'c': 
  270.          if ((tmp = atoi(*++argv)) || *argv[0]=='0') {
  271.            qclass = tmp;
  272.          } else if (tmp = StringToClass(*argv,0)) {
  273.            qclass = tmp;
  274.          } else {
  275.            printf("; invalid class specified\n");
  276.          }
  277.          break;
  278.        case 't': 
  279.          if ((tmp = atoi(*++argv)) || *argv[0]=='0') {
  280.            qtype = tmp;
  281.          } else if (tmp = StringToClass(*argv,0)) {
  282.            qtype = tmp;
  283.          } else {
  284.            printf("; invalid type specified\n");
  285.          }
  286.          break;
  287.        case 'x':
  288.          if (qtype == T_A) qtype = T_ANY;
  289.          addrc = *++argv;
  290.          addri=addrj=0;
  291.          while (*addrc) {
  292.            if (*addrc == '.') {
  293.          revaddr[addri][addrj++] = '.';
  294.          revaddr[addri][addrj] = (char) 0;
  295.          addri++; addrj=0;
  296.            } else {
  297.          revaddr[addri][addrj++] = *addrc;
  298.            }
  299.            addrc++;
  300.          }
  301.          if (*(addrc-1) == '.') {
  302.            addri--;
  303.          } else {
  304.            revaddr[addri][addrj++] = '.';
  305.            revaddr[addri][addrj] = (char) 0;
  306.          }
  307.          *domain = (char) 0;
  308.          for (addrj=addri; addrj>=0; addrj--)
  309.            strcat(domain,revaddr[addrj]);
  310.          strcat(domain,"in-addr.arpa.");
  311. /* old code -- some bugs
  312.          tmpaddr = inet_addr(*++argv);
  313.          pp = (char *) &tmpaddr;
  314.          sprintf(domain,"%d.%d.%d.%d.in-addr.arpa",
  315.              UC(pp[3]), UC(pp[2]), UC(pp[1]), UC(pp[0]));
  316. */        
  317.          break;
  318.        case 'p': port = htons(atoi(*++argv)); break;
  319.        case 'P':
  320.          if (argv[0][2] != NULL)
  321.            strcpy(pingstr,&argv[0][2]);
  322.          else
  323.            strcpy(pingstr,"ping -s");
  324.          break;
  325.        } /* switch - */
  326.        continue;
  327.      } /* if '-'   */
  328.  
  329.           if ((tmp = StringToType(*argv,-1)) != -1) { 
  330.         if ((T_ANY == tmp) && anyflag++) {  
  331.           qclass = C_ANY;     
  332.           continue; 
  333.         }
  334.         if (T_AXFR == tmp) {
  335.           pfcode = PRF_ZONE;
  336.           zone++;
  337.         } else {
  338.           qtype = tmp; 
  339.         }
  340.           }
  341.           else if ((tmp = StringToClass(*argv,-1)) != -1) { 
  342.         qclass = tmp; 
  343.           }     else {
  344.         bzero(domain,128);
  345.         sprintf(domain,"%s",*argv);
  346.           }
  347.         } /* while argv remains */
  348. if (pfcode & 0x80000)
  349.   printf("; pflag: %x res: %x\n", pfcode, _res.options);
  350.       
  351. /*
  352.  * Current env. (after this parse) is to become the
  353.  * new "working environmnet. Used in conj. with sticky.
  354.  */
  355.         if (envset) {
  356.           bcopy(&_res,Xres,sizeof(struct state));
  357.           Xpfcode=pfcode;
  358.           envset=0;
  359.         }
  360.  
  361. /*
  362.  * Current env. (after this parse) is to become the
  363.  * new default saved environmnet. Save in user specified
  364.  * file if exists else is SAVEENV (== "DiG.env").
  365.  */
  366.         if (envsave) {
  367.           if ((((afile= (char *) getenv("LOCALDEF")) != (char *) NULL) &&
  368.            ((fp=open(afile,O_WRONLY|O_CREAT|O_TRUNC,
  369.                  S_IREAD|S_IWRITE)) > 0)) ||
  370.           ((fp = open(SAVEENV,O_WRONLY|O_CREAT|O_TRUNC,
  371.                    S_IREAD|S_IWRITE)) > 0)) {
  372.         write(fp,&_res,sizeof(struct state));
  373.         write(fp,&pfcode,sizeof(int));
  374.         close(fp);
  375.           }
  376.           envsave=0;
  377.         }
  378.  
  379.         if (pfcode & PRF_CMD)
  380.           printf("%s\n",cmd);
  381.  
  382.       addrflag=anyflag=0;
  383.  
  384. /*
  385.  * Find address of server to query. If not dot-notation, then
  386.  * try to resolve domain-name (if so, save and turn off print 
  387.  * options, this domain-query is not the one we want. Restore
  388.  * user options when done.
  389.  * Things get a bit wierd since we need to use resolver to be
  390.  * able to "put the resolver to work".
  391.  */
  392.  
  393.    srvbuf[0]=0;
  394.    srvmsg=defsrv;
  395.    if (srv != NULL) {
  396.      tmpaddr = inet_addr(srv);
  397.      if ((tmpaddr != (unsigned)-1) || 
  398.      (strncmp("255.255.255.255",srv,15) == 0)) {
  399.        _res.nscount = 1;
  400.        _res.nsaddr.sin_addr.s_addr = tmpaddr;
  401.        srvmsg = strcat(srvbuf, srv);
  402.      } else {
  403.       Tpfcode=pfcode;
  404.       pfcode=0;
  405.       bcopy(&_res,Tres,sizeof(_res));
  406.       Toptions = _res.options;
  407.       _res.options = RES_DEFAULT;
  408.       res_init();
  409.       hp = gethostbyname(srv);
  410.       pfcode=Tpfcode;
  411.       if (hp == NULL) {
  412.     fflush(stdout);
  413.     fprintf(stderr,
  414.         "; Bad server: %s -- using default server and timer opts\n",
  415.         srv);
  416.     fflush(stderr);
  417.         srvmsg = defsrv;
  418.     srv = NULL;
  419.     _res.options = Toptions;
  420.       } else {
  421.     bcopy(Tres,&_res,sizeof(_res));
  422.     bcopy(hp->h_addr, &_res.nsaddr_list[0].sin_addr, hp->h_length);
  423.     _res.nscount = 1;
  424.         srvmsg = strcat(srvbuf,srv);
  425.         strcat(srvbuf, "  ");
  426.         strcat(srvmsg,inet_ntoa(_res.nsaddr.sin_addr));
  427.       }
  428.     }
  429.      _res.id += _res.retry;
  430.    }
  431.  
  432.        _res.id += _res.retry;
  433. /*       _res.options |= RES_DEBUG;  */
  434.        _res.nsaddr.sin_family = AF_INET;
  435.        _res.nsaddr.sin_port = port;
  436.  
  437.        if (zone) {
  438.      do_zone(domain,qtype);
  439.      if (pfcode & PRF_STATS) {
  440.        gettimeofday(&exectime,NULL);
  441.        printf(";; FROM: %s to SERVER: %s\n",curhost,srvmsg);
  442.        printf(";; WHEN: %s",ctime(&(exectime.tv_sec)));
  443.      }
  444.       
  445.      fflush(stdout);
  446.      continue;
  447.        }
  448.  
  449.        bytes_out = n = res_mkquery(QUERY, domain, qclass, qtype,
  450.                          (char *)0, 0, NULL, packet, sizeof(packet));
  451.        if (n < 0) {
  452.      fflush(stderr);
  453.      printf(";; res_mkquery: buffer too small\n\n");
  454.      continue;
  455.        }
  456.        eecode = 0;
  457.        if ((bytes_in = n = res_send(packet, n, answer, sizeof(answer))) < 0) {
  458.      fflush(stdout);
  459.          n = 0 - n;
  460.          msg[0]=0;
  461.          strcat(msg,";; res_send to server ");
  462.          strcat(msg,srvmsg);
  463.      perror(msg);
  464.      fflush(stderr);
  465.  
  466. #ifndef RESLOCAL
  467. /*
  468.  * resolver does not currently calculate elapsed time
  469.  * if there is an error in res_send()
  470.  */
  471. /*
  472.      if (pfcode & PRF_STATS) {
  473.        printf(";; Error time: "); prnttime(&hqtime); putchar('\n');
  474.      }
  475. */
  476. #endif
  477.      if (!dofile) {
  478.             if (eecode)
  479.           exit(eecode);
  480.         else
  481.           exit(9);
  482.       }
  483.        }
  484. #ifndef RESLOCAL
  485.        else {
  486.      if (pfcode & PRF_STATS) {
  487.        printf(";; Sent %d pkts, answer found in time: ",hqcount);
  488.        prnttime(&hqtime);
  489.        if (hxcount)
  490.          printf(" sent %d too many pkts",hxcount);
  491.        putchar('\n');
  492.      }
  493.        }
  494. #endif
  495.  
  496.        if (pfcode & PRF_STATS) {
  497.      gettimeofday(&exectime,NULL);
  498.      gethostname(curhost,30);
  499.      printf(";; FROM: %s to SERVER: %s\n",curhost,srvmsg);
  500.      printf(";; WHEN: %s",ctime(&(exectime.tv_sec)));
  501.          printf(";; MSG SIZE  sent: %d  rcvd: %d\n", bytes_out, bytes_in);
  502.        }
  503.       
  504.        fflush(stdout);
  505. /*
  506.  *   Argh ... not particularly elegant. Should put in *real* ping code.
  507.  *   Would necessitate root priviledges for icmp port though!
  508.  */
  509.        if (*pingstr) {
  510.          sprintf(doping,"%s %s 56 3 | tail -3",pingstr,
  511.          (srv==NULL)?(defsrv+10):srv);
  512.      system(doping);
  513.        }
  514.        putchar('\n');
  515.  
  516. /*
  517.  * Fairly crude method and low overhead method of keeping two
  518.  * batches started at different sites somewhat synchronized.
  519.  */
  520.        gettimeofday(&tv2, NULL);
  521.        tv1.tv_sec += wait;
  522.        difftv(&tv1,&tv2,&tv3);
  523.        if (tv3.tv_sec > 0)
  524.      sleep(tv3.tv_sec);
  525.       }
  526.     return(eecode);
  527.       }
  528.